package dungeonPackage;

import squareBorderPackage.*;

/**
 *  A class of Shafts containing maxCoordinates, squares, shaftDirections and a motherDungeon.
 *  
 * @param 	<E>
 * 			The type of squares the dungeon can contain.
 * 
 * @version	1.0
 * @author 	Esther Alberts & Jessa Bekker
 */
public class Shaft<E extends Square> extends SingularDungeon<E> {

	/**
	 * Initialize a new Shaft with given max coordinates.
	 * 
	 * @effect	This new Shaft is initialized as a dungeon with the given maxCoordinates.
	 * 			|super(maxCoordinates)
	 */
	public Shaft(Orientation maxCoordinates) {
		super(maxCoordinates);
		if(maxCoordinates.getX() != 0){
			shaftDirections[0] = Direction.EAST;
			shaftDirections[1] = Direction.WEST;
		}
		if(maxCoordinates.getY() != 0){
			shaftDirections[0] = Direction.SOUTH;
			shaftDirections[1] = Direction.NORTH;
		}
		if(maxCoordinates.getZ() != 0){
			shaftDirections[0] = Direction.CEILING;
			shaftDirections[1] = Direction.FLOOR;
		}
	}
	
	/**
	 * Check whether the given orientation is a valid orientation.
	 * 
	 * @return 	False if less than two coordinates are zero.
	 * 			| if(! (orientation.getX() != 0 && orientation.getY() == 0 && orientation.getZ() == 0
	 * 			|		|| orientation.getY() != 0 && orientation.getX() == 0 && orientation.getZ() == 0
	 * 			|		|| orientation.getZ() != 0 && orientation.getX() == 0 && orientation.getY() == 0))
	 */
	@Override
	public boolean isValidOrientation(Orientation orientation) {
		if (!super.isValidOrientation(orientation))
			return false;
		if(! (orientation.getX() != 0 && orientation.getY() == 0 && orientation.getZ() == 0
				|| orientation.getY() != 0 && orientation.getX() == 0 && orientation.getZ() == 0
				|| orientation.getZ() != 0 && orientation.getX() == 0 && orientation.getY() == 0))
			return false;
		return true;
	}
	
	/**
	 * Check whether by the addition of the given square at the given orientation in this shaft,
	 * a door would stand in between two squares of this shaft.
	 * 
	 * @return	True if and only if a door would stand in between the given square and an other
	 * 			square in this shaft.
	 * 			| if for some neighbor in getNeighbors(orientation) : 
	 * 			|	Door.class.isInstance(square.getBorderAt(orientation.getSharedBorderDirections(neighbor)[0])
	 * 			|		.getStrongestBorder(getSquareAt(neighbor).getBorderAt(orientation.getSharedBorderDirections(neighbor)[1])))
	 * 			| 	then (result == true)
	 * 			| else (result == false)
	 */
	public boolean doorInsertion(E square, Orientation orientation) {
		for(Orientation neighbor : getNeighbors(orientation)) {
			Direction[] borderDirections = orientation.getSharedBorderDirections(neighbor);
			Border[] borders = new Border[2];
			borders[0] = square.getBorderAt(borderDirections[0]);
			borders[1] = getSquareAt(neighbor).getBorderAt(borderDirections[1]);
			Border newBorder = borders[0].getStrongestBorder(borders[1]);
		    if (Door.class.isInstance(newBorder))
		    	return true;
		}
		return false;
	}
	
	/**
	 * Check whether this dungeon can have the given square at the given orientation.
	 * 
	 * @return	False if by setting the given square at the given orientation, a door would be
	 * 			in between them.
	 * 			| if(doorInsertion(square, orientation))
	 * 			| then result == false
	 * @return	False if the square is an instance of RockSquare
	 * 			|if(square instanceof RockSquare)
	 * 			| then result == false
	 */
	@Override
	public boolean canHaveAsSquareAt(E square, Orientation orientation) {
		if (!super.canHaveAsSquareAt(square, orientation))
			return false;
		if (doorInsertion(square, orientation))
			return false;
		if(square instanceof RockSquare)
			return false;
		return true;
	}

	/**
	 * @return the shaftDirections
	 */
	public Direction[] getShaftDirections() {
		return shaftDirections;
	}

	/**
	 * Array containing the directions in which squares of this shaft can have neighbors in this shaft. 
	 */
	private Direction[] shaftDirections = new Direction[2];
}